package com.kyl.file;

import com.kyl.base.ResponseResult;
import com.kyl.properties.MinIOConfigProperties;
import io.minio.MinioClient;
import io.minio.ObjectWriteResponse;
import io.minio.PutObjectArgs;
import io.minio.RemoveObjectArgs;
import io.minio.errors.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

/**
 * @author WanJl
 * @version 1.0
 * @title MinIOFileStorageServiceImpl
 * @description
 * @create 2024/7/3
 */
@Slf4j
@Service
public class MinIOFileStorageServiceImpl<I> implements FileStorageService {
    @Resource
    private MinioClient minioClient;

    @Resource
    private MinIOConfigProperties minIOConfigProperties;

    @Value("${kyl.framework.oss.minio.bucket}")
    private String bucket;

    @Value("${kyl.framework.oss.minio.endpoint}")
    private String endpoint;


    private static final String delimiter="/";

    /**
     * 设置文件路径的方法
     * @param dirPath
     * @param fileName
     * @return
     */
    private String buiderFilePath(String dirPath, String fileName) {
        StringBuilder stringBuilder = new StringBuilder();
        //重新生成文件名
        // 格式化时间
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        String todayStr = sdf.format(new Date());
        //把上传的文件都按照年月日进行分割  /2024/7/3/file.txt
        stringBuilder.append(todayStr).append(delimiter);
        //如果路径不为空
        if (StringUtils.isNotBlank(dirPath)){
            stringBuilder.append(dirPath).append(delimiter);//分隔符
        }
        //获取图片名后缀
        String suffix=fileName.substring(fileName.lastIndexOf("."));
        //随机生成图片名称
        String imageName= UUID.randomUUID().toString().replaceAll("-","");
        //追加图片名
        stringBuilder.append(imageName+suffix);
        return stringBuilder.toString();
    }


    public String quickUploadImageFile(MultipartFile file){
        //0、判断是否为空
        if (file.isEmpty()||file.getSize()==0){
            return "上传的图片不能为空";
        }

        //1、校验是否为图片文件
        try{
            BufferedImage bufferedImage = ImageIO.read(file.getInputStream());
        } catch (Exception e) {
            return "上传的文件不是图片";
        }
        String originalFilename = file.getOriginalFilename();

        //我们要分别获取文件的名和扩展名---我们的目的是要给这个图片重新取一个唯一的名字
        String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
        String fileName = com.kyl.utils.UUID.randomUUID()+extension;
        String imageFile;
        try {
            imageFile = uploadImageFile("", fileName, file.getInputStream());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        return endpoint+delimiter+bucket+ imageFile;
    }


    /**
     * 上传文件
     *
     * @param prefix      文件前缀
     * @param fileName    文件名
     * @param inputStream 文件流
     * @return 上传文件后，该文件的url
     */
    @Override
    public String uploadImageFile(String prefix, String fileName, InputStream inputStream) {
        //获取完整路径
        String filePath = buiderFilePath(prefix, fileName);
        try{
            //设置上传的文件配置信息
            PutObjectArgs imageProject = PutObjectArgs.builder()
                    .bucket(minIOConfigProperties.getBucket())//设置桶
                    .object(filePath)//文件路径
                    .contentType("image/jpeg")//文件类型
                    .stream(inputStream, inputStream.available(), -1)//文件流
                    .build();
            //上传图片
            ObjectWriteResponse objectWriteResponse = minioClient.putObject(imageProject);
            System.out.println("图片路径-----》"+objectWriteResponse.toString());
            System.out.println("图片路径id-----》"+objectWriteResponse.versionId());
            System.out.println("图片路径etag-----》"+objectWriteResponse.etag());
            System.out.println("图片路径object-----》"+objectWriteResponse.object());
            //生成上传文件后的url
            StringBuilder fileUrl=new StringBuilder();
            //fileUrl.append(delimiter+minIOConfigProperties.getBucket());
            fileUrl.append(delimiter+filePath);
            //把文件url返回
            return fileUrl.toString();

        } catch (IOException e) {
            log.error("minIO 上传文件错误-->",e);
            throw new RuntimeException("上传文件失败");
        } catch (ServerException e) {
            log.error("minIO 上传文件错误-->",e);
            throw new RuntimeException(e);
        } catch (InsufficientDataException e) {
            log.error("minIO 上传文件错误-->",e);
            throw new RuntimeException(e);
        } catch (ErrorResponseException e) {
            log.error("minIO 上传文件错误-->",e);
            throw new RuntimeException(e);
        } catch (NoSuchAlgorithmException e) {
            log.error("minIO 上传文件错误-->",e);
            throw new RuntimeException(e);
        } catch (InvalidKeyException e) {
            throw new RuntimeException(e);
        } catch (InvalidResponseException e) {
            log.error("minIO 上传文件错误-->",e);
            throw new RuntimeException(e);
        } catch (XmlParserException e) {
            log.error("minIO 上传文件错误-->",e);
            throw new RuntimeException(e);
        } catch (InternalException e) {
            log.error("minIO 上传文件错误-->",e);
            throw new RuntimeException(e);
        }finally {
            if(inputStream!=null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    /**
     * 删除文件
     *
     * @param fileUrl 文件url
     * @return 删除结果 true or false
     */
    @Override
    public boolean deleteFile(String fileUrl) {
        boolean flag=false;
        RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder()
                .bucket(minIOConfigProperties.getBucket())//设置桶
                .object(fileUrl)
                .build();
        log.info("图片删除成功");
        try {
            minioClient.removeObject(removeObjectArgs);
            flag=true;
        } catch (ErrorResponseException e) {
            throw new RuntimeException(e);
        } catch (InsufficientDataException e) {
            throw new RuntimeException(e);
        } catch (InternalException e) {
            throw new RuntimeException(e);
        } catch (InvalidKeyException e) {
            throw new RuntimeException(e);
        } catch (InvalidResponseException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        } catch (ServerException e) {
            throw new RuntimeException(e);
        } catch (XmlParserException e) {
            throw new RuntimeException(e);
        }finally {
            return flag;
        }

    }

    /**
     * 下载文件
     *
     * @param fileUrl 文件url
     * @return 文件字节码数组
     */
    @Override
    public byte[] downloadFile(String fileUrl) {
        return new byte[0];
    }
}
